package dk.twu.analyzer.core;

import dk.twu.analyzer.util.RTree;
import dk.twu.analyzer.util.VectorUtil;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Created by Tao Wu on 22/04/2015.
 */
public class GlobalIndex {
    public static final int MAX_ENTRIES = 100;
    public static final int MIN_ENTRIES = 50;
    private final Map<Window, RTree<String>> indexMap;

    public GlobalIndex(List<Window> windows, int dimSize) {
        indexMap = windows.stream().collect(Collectors.toMap((Function<Window, Window>) w -> w, w -> new RTree<>
                (MAX_ENTRIES, MIN_ENTRIES, dimSize, RTree.SeedPicker.LINEAR)));
    }

    public void insert(double[] value, Window window, String symbolKey) {
        indexMap.get(window).insert(value, symbolKey);
    }

    public Map<Window, List<String>> search(Map<LocalDateTime, Double> valueMap, double error) {
        double[] errorDimension = getErrorDim(error);
        Map<Window, double[]> searchValues = indexMap.keySet().stream().collect(Collectors.toMap(w -> w, w -> VectorUtil.flatToFirst(w.buildValue(valueMap))));
        Map<Window, List<String>> resultCollection = searchValues.entrySet().stream().collect(Collectors.toMap(windowEntry -> windowEntry.getKey(), windowEntry -> indexMap.get(windowEntry.getKey()).search(getSearchValue(windowEntry.getValue(), error), errorDimension)));
        return resultCollection;
    }

    private double[] getErrorDim(double error) {
        double[] errorDimension = new double[15];
        for (int i = 0; i < 15; i++) {
            errorDimension[i] = error * 2d;
        }
        return errorDimension;
    }

    private double[] getSearchValue(double[] value, double error) {
        double[] searchValue = new double[15];
        for (int i = 0; i < 15; i++) {
            searchValue[i] = value[i] - error;
        }
        return searchValue;
    }

    public List<Integer> size() {
        return indexMap.entrySet().stream().map(entry -> entry.getValue().size()).collect(Collectors.toList());
    }
}
